{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5764a009",
   "metadata": {},
   "source": [
    "### 环境安装"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b23cc956",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: http://mirrors.tencentyun.com/pypi/simple\n",
      "Requirement already satisfied: gym==0.26.2 in /home/ubuntu/.local/lib/python3.8/site-packages (0.26.2)\n",
      "Requirement already satisfied: cloudpickle>=1.2.0 in /home/ubuntu/.local/lib/python3.8/site-packages (from gym==0.26.2) (2.1.0)\n",
      "Requirement already satisfied: gym-notices>=0.0.4 in /home/ubuntu/.local/lib/python3.8/site-packages (from gym==0.26.2) (0.0.7)\n",
      "Requirement already satisfied: importlib-metadata>=4.8.0; python_version < \"3.10\" in /home/ubuntu/.local/lib/python3.8/site-packages (from gym==0.26.2) (4.12.0)\n",
      "Requirement already satisfied: numpy>=1.18.0 in /usr/local/lib/python3.8/dist-packages (from gym==0.26.2) (1.22.2)\n",
      "Requirement already satisfied: zipp>=0.5 in /usr/lib/python3/dist-packages (from importlib-metadata>=4.8.0; python_version < \"3.10\"->gym==0.26.2) (1.0.0)\n",
      "Looking in indexes: http://mirrors.tencentyun.com/pypi/simple\n",
      "Requirement already satisfied: pygame==2.3.0 in /home/ubuntu/.local/lib/python3.8/site-packages (2.3.0)\n"
     ]
    }
   ],
   "source": [
    "!pip install gym==0.26.2\n",
    "!pip install pygame==2.3.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0fbb6d13",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入gym库\n",
    "import gym\n",
    "\n",
    "# 创建CartPole环境，指定渲染模式为rgb_array，如果是在IDE中可以改为'human'\n",
    "env = gym.make('CartPole-v1', render_mode='rgb_array')\n",
    "# 重置环境\n",
    "env.reset()\n",
    "\n",
    "# 循环N次\n",
    "for i in range(10):\n",
    "    env.render() # 渲染环境\n",
    "    action = env.action_space.sample() # 从动作空间中随机选取一个动作\n",
    "    env.step(action) # 执行动作\n",
    "\n",
    "# 关闭环境\n",
    "env.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "052dbed5",
   "metadata": {},
   "source": [
    "### 工具类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "42f3d8a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在jupyter notebook里env.render看不到窗口\n",
    "# 写一个helper类，用matplotlib刷新显示图像\n",
    "# 初始化传入env，调用helper的render即可\n",
    "from IPython import display # 导入display模块，用于在Jupyter Notebook中显示图像\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt # 导入matplotlib库，用于绘制图像\n",
    "%matplotlib inline\n",
    "\n",
    "class GymHelper:\n",
    "    def __init__(self, env, figsize = (3, 3)):\n",
    "        self.env = env # 初始化Gym环境\n",
    "        self.figsize = figsize # 初始化绘图窗口大小\n",
    "        \n",
    "        plt.figure(figsize = figsize) # 创建绘图窗口\n",
    "        self.img = plt.imshow(env.render()) # 在绘图窗口中显示初始图像\n",
    "    \n",
    "    def render(self, title = None):\n",
    "        image_data = self.env.render() # 获取当前环境图像渲染数据\n",
    "        \n",
    "        self.img.set_data(image_data) # 更新绘图窗口中的图像数据\n",
    "        display.display(plt.gcf()) # 刷新显示\n",
    "        display.clear_output(wait = True) # 有新图片时再清除绘图窗口原有图像\n",
    "        if title: # 如果有标题，就显示标题\n",
    "            plt.title(title)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "6222cebe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 216x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 导入gym库\n",
    "import gym\n",
    "\n",
    "# 创建CartPole环境，指定渲染模式为rgb_array，如果是在IDE中可以改为'human'\n",
    "env = gym.make('CartPole-v1', render_mode='rgb_array')\n",
    "# 重置环境\n",
    "env.reset()\n",
    "# 创建GymHelper\n",
    "gym_helper = GymHelper(env)\n",
    "\n",
    "# 循环N次\n",
    "for i in range(10):\n",
    "    gym_helper.render(title = str(i)) # 渲染环境\n",
    "    action = env.action_space.sample() # 从动作空间中随机选取一个动作\n",
    "    env.step(action) # 执行动作\n",
    "\n",
    "# 关闭环境\n",
    "env.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d39a916",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
